import com.troyworks.datastructures.Array2;
import com.troyworks.datastructures.Array2D;
import com.troyworks.util.DesignByContract;
import com.troyworks.datastructures.ArrayWeighting;
/**
 * @author Troy Gardner
 */
class com.troyworks.datastructures.TestArray2 {

	public var REQUIRE : Function;
	public var ASSERT : Function;

	public function TestArray2() {
		DesignByContract.initialize(this);
		REQUIRE(testWeightedRandom(), "testWeightedRandom");
		REQUIRE(testArray2_concatEmpty(), "testArray2_concatEmpty");
		REQUIRE(testArray2_concatOne(), "testArray2_concatOne");
		REQUIRE(testArray2_concatMany(), "testArray2_concatMany");
		REQUIRE(testArray2_appendArray(), "testArray2_appendArray");
		REQUIRE(testArray2_unshift(), "testArray2_unshift");
		REQUIRE(testArray2_push(), "testArray2_push");
		REQUIRE(testArray2_pop(), "testArray2_pop");
		REQUIRE(testArray2_shift(), "testArray2_shift");
	}
	/*****************************************
	 * for a given bunch of elements, e.g. A, B,C
	 * and a given bunch of weightws e. 60, 30, 10
	 * get a random one that matches the approximate
	 * distrubtion of the weights.
	 */
	public function testWeightedRandom() : Boolean{
		var a : Array2 = new Array2("A","B", "C");
		var wts : Array = new Array(60, 30, 10);
		var weightor:ArrayWeighting = new ArrayWeighting();
		weightor.c = a;
		weightor.setWeights(wts);
		var res:Array2 = weightor.getWeightedRandom(null, 1000);
	    ///////////REVIEW HOW WELL THE FUNCTION DID ///////////////
		trace(" res " + res);
		res.sort();
		var stat : Object = new Object();
		for (var i : Number = 0; i < res.length; i++) {
			var ci : String = res[i];
	    	if(stat[ci] == null){
				stat[ci] = 1;
	    	}else{
				stat[ci]++;
	    	}
	    }
		for(var i in stat){
			var ci : Number = stat[i];
			trace(i + " found " + ci + " total of " + res.length + " = " + ci/res.length*100 +" %");
	    }
		return true;
		
	}
/*****************************************
	 * for a given bunch of elements, e.g. A, B,C
	 * and a given bunch of weightws e. 60, 30, 10
	 * get a random one that matches the approximate
	 * distrubtion of the weights.
	 */
	public function testWeightedRandeom() : Boolean{
		var a : Array2 = new Array2("A","B", "C");
		var wts : Array2 = new Array2(6, 3, 1);
		var W : Array2 = new Array2();

		var sum_of_wts : Number = 0;
		for (var i : Number = 0; i < wts.length; i++) {
			trace("sum of wts1 " + sum_of_wts);

			sum_of_wts = sum_of_wts +  wts[i];
			trace("sum of wts2 " + sum_of_wts);
			W[i] = sum_of_wts;
			
		}
		trace("sum_of_wts " + sum_of_wts + " array:" + W);

		var res : Array2 = new Array2();
		var count : Number = 1000;
	   
	    while(res.length < count){
			var passes : Boolean = false;
		    ////////////evaluate /////////////
		    while(!passes){
				var R : Number = Math.random()* sum_of_wts;
				//    trace("threshold "+ R + "-----------");
				for(var i = 0; i< W.length; i++){
					var cr = W[i];
				        if (R <= cr){
					        //trace("adding " + a[i]);
						res.push(a[i]);
						passes = true;
						break;
				        } else {
					       // 	trace("not adding " + a[i]); 
				        }
        	 		}
	        }   
	    }
	    ///////////REVIEW HOW WELL THE FUNCTION DID ///////////////
		trace(" res " + res);
		res.sort();
		var stat : Object = new Object();
		for (var i : Number = 0; i < res.length; i++) {
			var ci : String = res[i];
	    	if(stat[ci] == null){
				stat[ci] = 1;
	    	}else{
				stat[ci]++;
	    	}
	    }
		for(var i in stat){
			var ci : Number = stat[i];
			trace(i + " found " + ci + " total of " + res.length + " = " + ci/res.length*100 +" %");
	    }
		return true;
		
	}
	public function test2DArray() : Boolean{

		var a : Array2 = new Array2("A","B", "C");
		for(var i in a){
			trace(" k:'" + i + "' = v:'" +  a[i]+"'");
	}
		var a2D : Array2D = new Array2D( [1,2,3],[4,5,6],[7,8,9]);
		trace(util.Trace.me(a2D, " 2D array ", true));
		trace(" a2D lenght " + a2D.length + " " + a2D.getItem(2,2) + " " + a2D[2][2]);

		return true;
	}

	public function testArray2_filterNone() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(null, null, null, null);
		var passFilter:Boolean= (f1.toString() == "A,B,C");
		trace(" passFilterNone "  + passFilter );
		trace(" filtered  is " + f1);
		return passFilter;
	}

	public function testArray2_filterOne() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(null, null, ["A"]);
		var passFilter:Boolean= (f1.toString() == "B,C");
		trace(" passFilterOne "  + passFilter );
		trace(" filtered  is " + f1);
		return passFilter;
	}

	public function testArray2_filterAll() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(null, null, ["A", "B", "C"]);
		var passFilter:Boolean= (f1.toString() == "");
		trace(" passFilterAll "  + passFilter );
		trace(" filtered not is " + f1);
		return passFilter;
	}
	///////////////////////Filter To ] /////////////////////
	public function testArray2_filterNoneTo() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(null, 1, null, null);
		var passFilter:Boolean= (f1.toString() == "A");
		trace(" passFilterNone "  + passFilter );
		trace("filtered not is " + f1);
		return passFilter;
	}

	public function testArray2_filterOneTo() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(null, 1, null, ["A"]);
		var passFilter:Boolean= (f1.toString() == "A");
		trace(" testArray2_filterOneFrom "  + passFilter );
		trace("filtered not is " + f1);
		return passFilter;
	}

	public function testArray2_filterAllTo() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(null, 1, ["A", "B", "C"]);
		var passFilter:Boolean= (f1.toString() == "");
		trace(" passFilterAll "  + passFilter );
		trace("filtered not is " + f1);
		return true;
	}
	
	//////////////////////Filter from [---//////////////////////
	public function testArray2_filterNoneFrom() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(2, null, null, null);
		var passFilter:Boolean= (f1.toString() == "C");
		trace(" passFilterNone "  + passFilter );
		trace("filtered not is " + f1);
		return passFilter;
	}

	public function testArray2_filterOneFrom() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(2, null, ["A"]);
		var passFilter:Boolean= (f1.toString() == "C");
		trace(" testArray2_filterOneFrom "  + passFilter );
		trace("filtered not is " + f1);
		return passFilter;
	}

	public function testArray2_filterAllFrom() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var f1 : Array2 = a1.getFilteredSet(2, null, ["A", "B", "C"]);
		var passFilter:Boolean= (f1.toString() == "");
		trace(" passFilterAll "  + passFilter );
		trace("filtered not is " + f1);
		return passFilter;
	}
	public function testArray2_concatEmpty() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var b1 : Array2 = a1.concat();
		var passFilter:Boolean= (b1.toString() == "A,B,C");
		trace(" pass concat "  + passFilter );
		trace("  concat is " + b1);
		return passFilter;
	}
	public function testArray2_concatOne() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var b1 : Array2 = a1.concat("D");
		var passFilter:Boolean= (b1.toString() == "A,B,C,D");
		trace(" pass concat "  + passFilter );
		trace("  concat is " + b1);
		return passFilter;
	}
	public function testArray2_concatMany() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var b1 : Array2 = a1.concat(["D","E","F"]);
		var passFilter:Boolean= (b1.toString() == "A,B,C,D,E,F");
		trace("  pass concat "  + passFilter );
		trace("  concat is " + b1);
		return passFilter;
	}
	public function testArray2_appendArray() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		a1.appendArray(["D","E","F"]);
		var passFilter:Boolean= (a1.toString() == "A,B,C,D,E,F");
		trace("  pass appendArray: "  + passFilter );
		trace("  res is " + a1);
		return passFilter;
	}
	public function testArray2_unshift() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		a1.unshift(0);
		var passFilter:Boolean= (a1.toString() == "0,A,B,C");
		trace("  pass unshift: "  + passFilter );
		trace("  res is " + a1);
		return passFilter;
	}	
	public function testArray2_push() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var r:Number = a1.push("D","E");
		var passFilter:Boolean= (a1.toString() == "A,B,C,D,E") && r == 5;
		trace("  pass push: "  + passFilter );
		trace("  res is " + a1  + " r " + r);
		return passFilter;
	}	
	public function testArray2_pop() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var r:Object = a1.pop();
		var passFilter:Boolean= (a1.toString() == "A,B"  && r =="C");
		trace("  pass pop: "  + passFilter );
		trace("  res is " + a1 + " returned " + r);
		return passFilter;
	}	
	public function testArray2_shift() : Boolean{
		var a1 : Array2 = new Array2("A","B","C");
		var r:Object = a1.shift();
		var passFilter:Boolean= (a1.toString() == "B,C"  && r =="A");
		trace("  pass shift: "  + passFilter );
		trace("  res is " + a1 + " returned " + r);
		return passFilter;
	}	
}